package com.dreamlike.demo.HttpUtil.Core.ResponseBodyHandler;

import com.dreamlike.demo.HttpUtil.Core.HttpDefinition;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.Future;

public class JsonResponseBodyHandler implements StringResponseBodyHandler<Object>{
    public interface ObjectGenerator{
        Object generate(HttpDefinition httpDefinition,String body);
    }

    public ObjectGenerator objectGenerator;

    private static final ObjectMapper objectMapper= new ObjectMapper();

    public JsonResponseBodyHandler(ObjectGenerator objectGenerator) {
        this.objectGenerator = objectGenerator;
    }
    public JsonResponseBodyHandler(){
        objectGenerator = this::transToObject;
    }


    //只解决单层
    @SneakyThrows
    public Object transToObject(HttpDefinition httpDefinition,String body){
        Type returnType;
        Method method = httpDefinition.getMethod();
        if (body.isBlank()) {
            body = "{}";
        }
        if (Future.class.isAssignableFrom(method.getReturnType())) {
            returnType = ((ParameterizedType) method.getGenericReturnType())
                    .getActualTypeArguments()[0];
        }else {
            returnType = method.getGenericReturnType();
        }

        if (returnType instanceof ParameterizedType){
            ParameterizedType parameterizedType = (ParameterizedType) returnType;
            JavaType type = objectMapper.getTypeFactory().constructParametricType((Class<?>) parameterizedType.getRawType(),typesCastToClass(parameterizedType.getActualTypeArguments()));
            return objectMapper.readValue(body, type);
        }

        return objectMapper.readValue(body, ((Class) returnType));
    }

    private Class[] typesCastToClass(Type[] ts){
        Class[] classes = new Class[ts.length];
        for (int i = 0; i < ts.length; i++) {
            classes[i] = (Class) ts[i];
        }
        return classes;
    }


    @Override
    public Object trans(HttpDefinition httpDefinition, String body) {
        return objectGenerator.generate(httpDefinition, body);
    }
}
